package com.zmn.oms.dubbo.impl.zmn.channel.docking;

import com.alibaba.dubbo.config.annotation.Service;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.consts.GlobalConsts;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.dubbo.dto.zmn.channel.*;
import com.zmn.oms.dubbo.dto.zmn.order.OrderWorkDRO;
import com.zmn.oms.dubbo.interfaces.zmn.channel.docking.ChannelDockingRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.model.dto.order.open.AvailableTimeslotsQuery;
import com.zmn.oms.model.dto.order.proxy.*;
import com.zmn.oms.model.dto.product.OrderProductDTO;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.vo.order.open.AvailableTimeslotsVO;
import com.zmn.oms.model.vo.order.open.OrderInfoVO;
import com.zmn.oms.model.vo.work.ZsOrderWorkVO;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.business.interfaces.docking.ChannelDockingBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkQueryBService;
import com.zmn.oms.zmn.business.interfaces.work.autoflow.WorkFlowContextBService;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;


import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 类描述：渠道订单服务
 * @author xiewenbing
 * @since 2021/3/18 18:16
 */
@SuppressWarnings("ALL")
@Slf4j
@Service(loadbalance = "roundrobin", timeout = 20000, retries = 2, version = DubboConsts.INTERFACE_VERSION, validation = "false")
public class ChannelDockingRemoteServiceImpl implements ChannelDockingRemoteService {

    @Autowired
    private ChannelDockingBService channelDockingBService;

    @Autowired
    private WorkFlowContextBService workFlowContextBService;

    @Autowired
    private OrderWorkService orderWorkService;

    @Autowired
    private ZsOrderWorkQueryBService zsOrderWorkQueryBService;

    // TODO try catch OmsBaseException change Exception 2021-05-19
    /**
     * 查询可预约时间
     *
     * @param availableTimeslotsQueryDIO
     * @return
     */
    @Override
    @ApiOperation(value = "查询订单平台可预约时间")
    public ResponseDTO<List<AvailableTimeslotsDRO>> queryAvailableTimeslots(@ApiParam(value = "查询参数") @NotNull(message = "参数不能为空") AvailableTimeslotsQueryDIO availableTimeslotsQueryDIO) {

        try{
            AvailableTimeslotsQuery availableTimeslotsQuery = BeanMapper.map(availableTimeslotsQueryDIO,AvailableTimeslotsQuery.class);
            List<AvailableTimeslotsVO> availableTimeslotsVOList =  channelDockingBService.queryAvailableTimeslots(availableTimeslotsQuery);

            List<AvailableTimeslotsDRO> availableTimeslotsDROList = BeanMapper.mapList(availableTimeslotsVOList,AvailableTimeslotsDRO.class);

            return ResponseDTO.success(availableTimeslotsDROList);
        } catch (OmsBaseException exception) {
            return ResponseDTO.fail(exception.getMessage());
        }
    }

    /**
     * 通过订单id和渠道id查询订单详情
     *
     * @param channelOrderQueryDIO
     * @return
     */
    @Override
    @ApiOperation(value = "查询渠道订单详情")
    public ResponseDTO<OrderInfoDRO> queryChannelOrder(@ApiParam(value = "查询参数") @NotNull(message = "参数不能为空")ChannelOrderQueryDIO channelOrderQueryDIO) {

        try {
            OrderInfoVO orderInfoVO = channelDockingBService.queryOrder(channelOrderQueryDIO.getOrderId(),channelOrderQueryDIO.getChannelId());
            OrderInfoDRO orderInfoDRO = BeanMapper.map(orderInfoVO,OrderInfoDRO.class);
            orderInfoDRO.setServItems(BeanMapper.mapList(orderInfoVO.getServiceItems(), OrderServiceItemDRO.class));

            return ResponseDTO.success(orderInfoDRO);
        } catch(OmsBaseException exception) {
            return ResponseDTO.fail(exception.getMessage());
        }
    }

    /**
     * 通过订单id和渠道id查询订单详情
     *
     * @param outerId
     * @param channelId
     * @return
     */
    @Override
    @ApiOperation(value = "查询渠道订单详情")
    public ResponseDTO<OrderInfoDRO> queryChannelOrderByOuterId(@ApiParam(value = "渠道订单id") @NotNull(message = "渠道订单id不能为空")String outerId,
                                                         @ApiParam(value = "渠道id") Integer channelId) {

        ZsOrderWorkVO orderWorkVO ;
        try {
            orderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterId(outerId, channelId);
        } catch (Exception exception) {
            log.info("[ChannelDockingRemoteService][queryChannelOrderByOuterId] throw exception,[{}][{}][{}][{}]",
                    outerId, channelId, exception.getMessage(),exception.toString());
            return ResponseDTO.fail("查询异常");
        }

        if (Objects.isNull(orderWorkVO)) {
            return ResponseDTO.fail("查询失败，没有对应的工单");
        }

        ChannelOrderQueryDIO orderQueryDIO = new ChannelOrderQueryDIO();
        orderQueryDIO.setOrderId(orderWorkVO.getOrderId());
        orderQueryDIO.setChannelId(channelId);

        return queryChannelOrder(orderQueryDIO);
    }
    /**
     * 渠道订单取消
     * @param cancelOrderDIO
     * @return
     */
    @Override
    @ApiOperation(value = "渠道订单取消")
    public ResponseDTO cancelOrder(@ApiParam(value = "订单取消参数") @NotNull(message = "参数不能为空")CancelOrderDIO cancelOrderDIO) {

        try {
            CancelOrderDTO cancelOrderDTO = BeanMapper.map(cancelOrderDIO,CancelOrderDTO.class);

            if (cancelOrderDTO.getAgreeCancel() == null) {
                // 渠道申请取消，默认不校验是否存在待审核的取消申请 2022.07.22 by lhl
                cancelOrderDTO.setAgreeCancel(GlobalConsts.YES);
            }

            if (Objects.equals(cancelOrderDIO.getChannelCancel(), GlobalConsts.NO)) {

                cancelOrderDTO.setOperatorId(0L);
                cancelOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
                cancelOrderDTO.setOperator("系统");

            } else {
                cancelOrderDTO.setOperatorId((long) Optional.ofNullable(cancelOrderDIO.getChannelId()).orElse(0));
                cancelOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
                cancelOrderDTO.setOperator("渠道");
            }

            channelDockingBService.cancelOrder(cancelOrderDTO);
        } catch (OmsBaseException exception) {
            return ResponseDTO.fail(exception.getMessage());
        }

        return ResponseDTO.success();
    }

    /**
     * 渠道订单退款
     * @param refundOrderDIO
     * @return
     */
    @Override
    @ApiOperation(value = "渠道订单退款")
    public ResponseDTO refundOrder(@ApiParam(value = "订单退款参数") @NotNull(message = "参数不能为空")RefundOrderDIO refundOrderDIO) {

        try {
            CancelOrderDTO cancelOrderDTO = BeanMapper.map(refundOrderDIO,CancelOrderDTO.class);

            if (Objects.equals(refundOrderDIO.getChannelRefund(), GlobalConsts.NO)) {

                cancelOrderDTO.setOperatorId(0L);
                cancelOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
                cancelOrderDTO.setOperator("系统");

            } else {
                cancelOrderDTO.setOperatorId((long) Optional.ofNullable(refundOrderDIO.getChannelId()).orElse(0));
                cancelOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);
                cancelOrderDTO.setOperator("渠道");
            }

            cancelOrderDTO.setRefundCancel(GlobalConsts.YES);

            channelDockingBService.cancelOrder(cancelOrderDTO);
        } catch (OmsBaseException exception) {
            return ResponseDTO.fail(exception.getMessage());
        }

        return ResponseDTO.success();
    }

    /**
     * 渠道订单支付，包括预付和二次支付
     * @param channelPayOrderDIO
     * @return
     */
    @Override
    @ApiOperation(value = "渠道支付订单")
    public ResponseDTO channelPayOrder(@ApiParam(value = "订单预付参数") @NotNull(message = "参数不能为空")ChannelPayOrderDIO channelPayOrderDIO) {

        try {
            PayOrderDTO payOrderDTO = BeanMapper.map(channelPayOrderDIO,PayOrderDTO.class);

            payOrderDTO.setOperator("系统");
            payOrderDTO.setOperatorId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
            payOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);

            channelDockingBService.payOrder(payOrderDTO);

            // 工单自动流转
            if (Objects.nonNull(channelPayOrderDIO.getOrderAutoFlow()) && channelPayOrderDIO.getOrderAutoFlow()) {
                workFlowContextBService.asyncAutoFlow(payOrderDTO.getOrderId(), payOrderDTO.getOrderId());
            }

        } catch (OmsBaseException omsBaseException) {
            log.info("ChannelDockingRemoteService.channelPayOrder occur OmsBaseException:[{}][{}][{}]", channelPayOrderDIO.getOrderId(),
                    omsBaseException.getMessage(), omsBaseException);
            return ResponseDTO.fail(omsBaseException.getMessage());
        } catch (Exception exception) {
            log.info("ChannelDockingRemoteService.channelPayOrder occur exception:[{}][{}][{}]", channelPayOrderDIO.getOrderId(),
                    exception.getMessage(), exception);
            return ResponseDTO.fail(String.format("支付失败:%s", exception.getMessage()));
        }

        return ResponseDTO.success();
    }

    /**
     * 创建标准渠道订单
     * @param createChannelOrderDIO
     * @return
     */
    @Override
    @ApiOperation(value = "创建标准渠道订单")
    public ResponseDTO<OrderWorkDRO> createOrder(@ApiParam(value = "订单创建参数") @NotNull(message = "参数不能为空")CreateChannelOrderDIO createChannelOrderDIO) {

        try {
            CreateOrderDTO createOrderDTO = BeanMapper.map(createChannelOrderDIO,CreateOrderDTO.class);

            createOrderDTO.setOperator("系统");
            createOrderDTO.setOperatorId((long)GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
            createOrderDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_CHANNEL);

            // 优惠参数
            if (CollectionUtil.isNotNullOrEmpty(createChannelOrderDIO.getOrderDiscountList())) {
                List<OrderDiscountDTO> orderDiscountList = BeanMapper.mapList(createChannelOrderDIO.getOrderDiscountList(),OrderDiscountDTO.class);
                createOrderDTO.setOrderDiscountList(orderDiscountList);
            }

            // 产品列表
            if (CollectionUtil.isNotNullOrEmpty(createChannelOrderDIO.getOrderProductList())) {
                List<OrderProductDTO> orderProductList = BeanMapper.mapList(createChannelOrderDIO.getOrderProductList(),OrderProductDTO.class);
                createOrderDTO.setOrderProductList(orderProductList);
            }

            // 保存订单
            OrderWork orderWork = channelDockingBService.createOrder(createOrderDTO);

            if (Objects.equals(createChannelOrderDIO.getAutoFlow(),Boolean.TRUE)) {
                // 工单自动流转
                workFlowContextBService.asyncAutoFlow(orderWork.getOrderId(), orderWork.getWorkId());
            }

            OrderWorkDRO orderWorkDRO = BeanMapper.map(orderWork,OrderWorkDRO.class);
            return ResponseDTO.success(orderWorkDRO);

        } catch (OmsBaseException omsBaseException) {
            return ResponseDTO.fail(omsBaseException.getMessage());
        } catch (Exception exception) {
            return ResponseDTO.fail("创建订单失败");
        }
    }

    /**
     * 通过渠道id和渠道订单id查询工单详情
     * @param outerId
     * @param channelId
     * @return
     */
    @Override
    @ApiOperation(value = "查询工单详情")
    public ResponseDTO<OrderWorkDRO> findOrderWorkByChannelAndOuterId(@ApiParam(value = "渠道订单id") @NotNull(message = "渠道订单id不能为空")String outerId,
                                                               @ApiParam(value = "渠道id") Integer channelId) {

        ZsOrderWorkVO orderWorkVO;
        try {

            orderWorkVO = zsOrderWorkQueryBService.findOrderWorkByOuterId(outerId, channelId);

        } catch (Exception exception) {

            log.info("[ChannelDockingRemoteService][findOrderWorkByChannelAndOuterId] throw exception,[{}][{}][{}][{}]",
                    outerId, channelId, exception.getMessage(),exception.toString());
            return ResponseDTO.fail("查询异常");
        }

        if (Objects.isNull(orderWorkVO)) {
            return ResponseDTO.fail("查询失败，没有对应的工单");
        }

        return findOrderWorkById(orderWorkVO.getOrderId(),orderWorkVO.getWorkId());
    }

    /**
     * 通过工单id查询工单详情
     * @return
     */
    @Override
    @ApiOperation(value = "查询工单详情")
    public ResponseDTO<OrderWorkDRO> findOrderWorkById(@ApiParam(value = "订单id") @NotNull(message = "订单id不能为空")Long orderId,
                                                       @ApiParam(value = "工单id") @NotNull(message = "工单id不能为空")Long workId) {

        try {

            OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
            if (Objects.isNull(orderWork)) {
                orderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderId, workId);
            }

            if (Objects.nonNull(orderWork)) {
                OrderWorkDRO orderWorkDRO = BeanMapper.map(orderWork, OrderWorkDRO.class);
                return ResponseDTO.success(orderWorkDRO);
            }
        } catch (Exception exception) {
            log.info("[ChannelDockingRemoteService][findOrderWorkById] throw exception,[{}][{}][{}][{}]",
                    orderId, workId, exception.getMessage(),exception.toString());
            return ResponseDTO.fail("查询异常");
        }

       return ResponseDTO.fail("查询失败，没有对应的工单");
    }

    /**
     * 添加订单日志
     * @param orderLogDIO
     * @return
     */
    @Override
    @ApiOperation(value = "添加订单日志")
    public ResponseDTO saveOrderLog(@ApiParam(value = "订单日志参数") @NotNull(message = "参数不能为空")OrderLogDIO orderLogDIO) {

        try {
            OrderLogDTO orderLogDTO = BeanMapper.map(orderLogDIO, OrderLogDTO.class);
            orderLogDTO.setOperatorLogRemark(orderLogDIO.getContent());

            channelDockingBService.saveOrderLog(orderLogDTO);

        } catch(OmsBaseException exception) {
            return ResponseDTO.fail(exception.getMessage());
        }

        return ResponseDTO.success("成功");
    }

    /**
     * 添加订单评价
     * @param orderCommentDIO
     * @return
     */
    @Override
    @ApiOperation(value = "添加订单评价")
    public ResponseDTO saveOrderComment(@ApiParam(value = "订单评价参数") @NotNull(message = "参数不能为空")OrderCommentDIO orderCommentDIO) {

        try {
            CommentDTO orderCommentDTO = BeanMapper.map(orderCommentDIO, CommentDTO.class);

            channelDockingBService.saveOrderComment(orderCommentDTO);

        } catch(OmsBaseException exception) {
            return ResponseDTO.fail(exception.getMessage());
        }

        return ResponseDTO.success("成功");
    }

    /**
     * 修改订单信息，包括预约时间，用户地址和电话，渠道订单id，渠道扩展信息，渠道预付状态，可弃单状态等
     * @param updateOrderDIO
     * @return
     */
    @Override
    @ApiOperation(value = "修改订单信息")
    public ResponseDTO updateOrder(@ApiParam(value = "订单修改参数") @NotNull(message = "参数不能为空")UpdateOrderDIO updateOrderDIO) {

        try {
            UpdateOrderDTO updateOrderDTO = BeanMapper.map(updateOrderDIO, UpdateOrderDTO.class);

            channelDockingBService.updateOrder(updateOrderDTO);

        } catch(OmsBaseException exception) {
            return ResponseDTO.fail(exception.getMessage());
        }

        return ResponseDTO.success("成功");
    }

    /**
     * 订单自动流转
     * @param orderId
     * @param workId
     * @return
     */
    @Override
    @ApiOperation(value = "订单自动流转")
    public ResponseDTO orderAutoFlow(@ApiParam(value = "订单id") @NotNull(message = "订单id不能为空")Long orderId,
                              @ApiParam(value = "工单id") @NotNull(message = "工单id不能为空")Long workId) {

        try {
            workFlowContextBService.asyncAutoFlow(orderId, workId);
        } catch(Exception exception) {
            return ResponseDTO.fail(exception.getMessage());
        }

        return ResponseDTO.success("成功");
    }
    /**
     * 发起工单自动跟单
     * @param orderAutoTrackDIO
     * @return
     */
    @Override
    @ApiOperation(value = "起工单自动跟单")
    public ResponseDTO updateOrderAutoTrack(@ApiParam(value = "工单自动跟单参数") @NotNull(message = "参数不能为空")OrderAutoTrackDIO orderAutoTrackDIO) {

        try {
            OrderAutoTrackDTO orderAutoTrackDTO = BeanMapper.map(orderAutoTrackDIO, OrderAutoTrackDTO.class);

            channelDockingBService.updateOrderAutoTrack(orderAutoTrackDTO);

        } catch(OmsBaseException exception) {
            return ResponseDTO.fail(exception.getMessage());
        }

        return ResponseDTO.success("成功");
    }

    /**
     * 查询订单备注
     * @param queryOrderRemarkDIO
     * @return
     */
    @Override
    @ApiOperation(value = "查询订单备注")
    public ResponseDTO<String> queryOrderRemark(@ApiParam(value = "查询订单备注参数") @NotNull(message = "参数不能为空")QueryOrderRemarkDIO queryOrderRemarkDIO) {

        try {

            String remark = channelDockingBService.queryOrderRemark(queryOrderRemarkDIO.getOrderId(),queryOrderRemarkDIO.getWorkId(),
                    queryOrderRemarkDIO.getType());

            return ResponseDTO.success(remark,"成功");

        } catch(OmsBaseException exception) {
            return ResponseDTO.fail(exception.getMessage());
        }
    }
}
